package com.css.zfzx.fxpg.modules.casulaty.estimate.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSONObject;
import com.css.bpm.platform.org.division.repository.entity.DivisionEntity;
import com.css.zfzx.fxpg.common.utils.BeanUtil;
import com.css.zfzx.fxpg.common.utils.EasyPoiExcelUtil;
import com.css.zfzx.fxpg.modules.buildings.data.repository.FxBuildingsNativeRepository;
import com.css.zfzx.fxpg.modules.buildings.data.repository.entity.FxBuildingsEntity;
import com.css.zfzx.fxpg.modules.buildings.data.viewobjects.FxBuildingsQueryParams;
import com.css.zfzx.fxpg.modules.casulaty.estimate.repository.FxCasulatyEstimateNativeRepository;
import com.css.zfzx.fxpg.modules.casulaty.estimate.repository.FxCasulatyEstimateRepository;
import com.css.zfzx.fxpg.modules.casulaty.estimate.repository.entity.FxCasulatyEstimateEntity;
import com.css.zfzx.fxpg.modules.casulaty.estimate.service.FxCasulatyEstimateService;
import com.css.zfzx.fxpg.modules.casulaty.estimate.viewobjects.FxCasulatyEstimateManageVO;
import com.css.zfzx.fxpg.modules.casulaty.estimate.viewobjects.FxCasulatyEstimateQueryParams;
import com.css.bpm.platform.api.local.PlatformAPI;
import com.css.bpm.platform.sys.dict.repository.entity.DictItemEntity;
import com.css.bpm.platform.utils.*;
import com.css.zfzx.fxpg.modules.casulaty.estimate.viewobjects.FxCasulatyEstimateVO;
import com.css.zfzx.fxpg.modules.percent.casualty.repository.FxCasualtyPercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.casualty.repository.entity.FxCasualtyPercentEntity;
import com.css.zfzx.fxpg.modules.percent.casualty.viewobjects.FxCasualtyPercentQueryParams;
import com.css.zfzx.fxpg.modules.percent.damage.repository.FxDamagePercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.damage.repository.entity.FxDamagePercentEntity;
import com.css.zfzx.fxpg.modules.percent.damage.viewobjects.FxDamagePercentQueryParams;
import com.css.zfzx.fxpg.modules.percent.daynight.repository.FxDayNightPercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.daynight.repository.entity.FxDayNightPercentEntity;
import com.css.zfzx.fxpg.modules.percent.daynight.viewobjects.FxDayNightPercentQueryParams;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.FxVulnerabilityProvinceNativeRepository;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.entity.FxVulnerabilityProvinceEntity;
import com.css.zfzx.fxpg.modules.vulnerability.province.viewobjects.FxVulnerabilityProvinceQueryParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * @author leon
 * @date 2020-11-13
 */
@Service
@Slf4j
public class FxCasulatyEstimateServiceImpl implements FxCasulatyEstimateService {

    @Autowired
    private FxCasulatyEstimateRepository fxCasulatyEstimateRepository;
    @Autowired
    private FxCasulatyEstimateNativeRepository fxCasulatyEstimateNativeRepository;
    /**
     * 房屋数据Repository
     */
    @Autowired
    private FxBuildingsNativeRepository buildingsNativeRepository;
    /**
     * 建筑破坏损失比Repository
     */
    @Autowired
    private FxDamagePercentNativeRepository damagePercentNativeRepository;
    /**
     * 易损性
     */
    @Autowired
    private FxVulnerabilityProvinceNativeRepository provinceNativeRepository;
    /**
     * 昼夜
     */
    @Autowired
    private FxDayNightPercentNativeRepository dayNightPercentNativeRepository;
    /**
     * 伤亡率
     */
    @Autowired
    private FxCasualtyPercentNativeRepository casualtyPercentNativeRepository;

    @Override
    public JSONObject queryFxCasulatyEstimates(FxCasulatyEstimateQueryParams queryParams, int curPage, int pageSize) {
        Page<FxCasulatyEstimateEntity> fxCasulatyEstimatePage = this.fxCasulatyEstimateNativeRepository.queryFxCasulatyEstimates(queryParams, curPage, pageSize);
        JSONObject jsonObject = PlatformPageUtils.formatPageData(fxCasulatyEstimatePage);
        return jsonObject;
    }

    @Override
    public List<FxCasulatyEstimateEntity> listFxCasulatyEstimates(FxCasulatyEstimateQueryParams queryParams) {
        return fxCasulatyEstimateNativeRepository.listFxCasulatyEstimates(queryParams);
    }


    @Override
    public FxCasulatyEstimateEntity getFxCasulatyEstimate(String id) {
        FxCasulatyEstimateEntity fxCasulatyEstimate = this.fxCasulatyEstimateRepository.findById(id).orElse(null);
        return fxCasulatyEstimate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FxCasulatyEstimateEntity saveFxCasulatyEstimate(FxCasulatyEstimateEntity fxCasulatyEstimate) {
        String uuid = UUIDGenerator.getUUID();
        fxCasulatyEstimate.setId(uuid);
        fxCasulatyEstimate.setCreateUser(PlatformSessionUtils.getUserId());
        fxCasulatyEstimate.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        this.fxCasulatyEstimateRepository.save(fxCasulatyEstimate);
        return fxCasulatyEstimate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FxCasulatyEstimateEntity updateFxCasulatyEstimate(FxCasulatyEstimateEntity fxCasulatyEstimate) {
        fxCasulatyEstimate.setUpdateUser(PlatformSessionUtils.getUserId());
        fxCasulatyEstimate.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        String id = fxCasulatyEstimate.getId();
        FxCasulatyEstimateEntity one = fxCasulatyEstimateRepository.findById(id).get();
        BeanUtil.copyPropertiesIgnoreNull(fxCasulatyEstimate, one);
        this.fxCasulatyEstimateRepository.save(one);
        return fxCasulatyEstimate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFxCasulatyEstimates(List<String> ids) {
        List<FxCasulatyEstimateEntity> fxCasulatyEstimateList = this.fxCasulatyEstimateRepository.findAllById(ids);
        if (!PlatformObjectUtils.isEmpty(fxCasulatyEstimateList) && fxCasulatyEstimateList.size() > 0) {
            for (FxCasulatyEstimateEntity fxCasulatyEstimate : fxCasulatyEstimateList) {
                this.fxCasulatyEstimateRepository.delete(fxCasulatyEstimate);
            }
        }
    }

    @Override
    public List<DictItemEntity> getValidDictItemsByDictCode(String dictCode) {
        List<DictItemEntity> validDictItems = PlatformAPI.getDictAPI().getValidDictItemsByDictCode(dictCode);
        return validDictItems;
    }

    @Override
    public String exportExcel(FxCasulatyEstimateQueryParams queryParams, HttpServletResponse response) {
        try {
            List<FxCasulatyEstimateEntity> casulatyEstimateEntities = fxCasulatyEstimateNativeRepository.listFxCasulatyEstimates(queryParams);
            // 深拷贝
            ArrayList<FxCasulatyEstimateVO> vos = new ArrayList<>();
            for (FxCasulatyEstimateEntity casulatyEstimateEntity : casulatyEstimateEntities) {
                FxCasulatyEstimateVO vo = new FxCasulatyEstimateVO();
                BeanUtils.copyProperties(casulatyEstimateEntity, vo);
                vos.add(vo);
            }
            // 导出
            EasyPoiExcelUtil.exportExcel(vos, "人员伤亡损失评估信息统计", "人员伤亡损失评估信息", FxCasulatyEstimateVO.class, "人员伤亡损失评估.xlsx", response);
            return "导出成功";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @Override
    public String exportManageExcel(FxCasulatyEstimateQueryParams queryParams, HttpServletResponse response) {
        try {
            List<FxCasulatyEstimateEntity> casulatyEstimateEntities = fxCasulatyEstimateNativeRepository.listFxCasulatyEstimates(queryParams);
            // 深拷贝
            ArrayList<FxCasulatyEstimateManageVO> vos = new ArrayList<>();
            for (FxCasulatyEstimateEntity casulatyEstimateEntity : casulatyEstimateEntities) {
                FxCasulatyEstimateManageVO vo = new FxCasulatyEstimateManageVO();
                BeanUtils.copyProperties(casulatyEstimateEntity, vo);
                vos.add(vo);
            }
            // 导出
            EasyPoiExcelUtil.exportExcel(vos, "人员伤亡中间结果管理", "人员伤亡中间结果管理", FxCasulatyEstimateManageVO.class, "人员伤亡中间结果管理.xlsx", response);
            return "导出成功";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @Override
    public String importExcel(MultipartFile file) {
        try {
            // 返回的消息
            StringBuilder returnMsg = new StringBuilder();
            // 导入的参数信息
            ImportParams params = new ImportParams();
            // 设置解析从第1+1+1行开始
            params.setTitleRows(1);
            params.setHeadRows(1);
            // 是否需要校验
            params.setNeedVerify(true);
            // 获取到Excel数据
            ExcelImportResult<FxCasulatyEstimateManageVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), FxCasulatyEstimateManageVO.class, params);
            List<FxCasulatyEstimateManageVO> list = result.getList();
            // 批量新增
            this.saveExcel(list);
            returnMsg.append("成功导入" + result.getList().size() + "条，失败" + result.getFailList().size() + "条<br/>");
            if (result.isVerifyFail()) {
                // 校验返回失败行信息
                Iterator<FxCasulatyEstimateManageVO> iterator = result.getFailList().iterator();
                while (iterator.hasNext()) {
                    FxCasulatyEstimateManageVO vo = iterator.next();
                    String error = "";
                    returnMsg.append("第" + vo.getRowNum() + "行" + vo.getErrorMsg() + "<br/>");
                    returnMsg.append(error);
                }
            }
            return returnMsg.toString();
        } catch (RuntimeException e) {
            log.error(e.getMessage(), e);
            return e.getMessage();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            if ("库中该数据最多一条，请管理员清理数据库冗余数据！".equals(e.getMessage())) {
                return e.getMessage();
            } else {
                return "导入失败，请检查数据正确性";
            }
        }
    }

    private void saveExcel(List<FxCasulatyEstimateManageVO> list) {
        for (int i = 0; i < list.size(); i++) {
            FxCasulatyEstimateEntity entity = new FxCasulatyEstimateEntity();
            FxCasulatyEstimateManageVO vo = list.get(i);
            // 将VO数据映射拷贝到库表中
            BeanUtils.copyProperties(vo, entity);
            saveOrUpdate(entity);
        }
    }

    /**
     * 保存或者修改
     *
     * @param entity
     */
    private void saveOrUpdate(FxCasulatyEstimateEntity entity) {
        FxCasulatyEstimateQueryParams queryParams = new FxCasulatyEstimateQueryParams();
        // 省市区
        queryParams.setProvince(entity.getProvince());
        queryParams.setCity(entity.getCity());
        queryParams.setArea(entity.getArea());
        // 烈度人员伤亡、时间段、破坏程度
        queryParams.setIntensity(entity.getIntensity());
        queryParams.setCasulaty(entity.getCasulaty());
        queryParams.setPeriod(entity.getPeriod());
        queryParams.setDamageDegree(entity.getDamageDegree());
        // 查询库数据
        List<FxCasulatyEstimateEntity> entities = fxCasulatyEstimateNativeRepository.listFxCasulatyEstimates(queryParams);
        // 若查到数据为空，则新增
        if (CollectionUtils.isEmpty(entities)) {
            this.saveFxCasulatyEstimate(entity);
        } else {
            if (entities.size() == 1) {
                FxCasulatyEstimateEntity sourceEntity = entities.get(0);
                BeanUtil.copyPropertiesIgnoreNull(entity, sourceEntity);
                this.updateFxCasulatyEstimate(sourceEntity);
            } else {
                throw new RuntimeException("库中该数据最多一条，请管理员清理数据库冗余数据！");
            }
        }
    }

    @Override
    public String calculate(FxCasulatyEstimateQueryParams queryParams) {
        try {
            // 伤亡估计表：根据参数查询出需要的数据list;每个区最多80条数据
            List<FxCasulatyEstimateEntity> all = fxCasulatyEstimateNativeRepository.listFxCasulatyEstimates(queryParams);
            // 房屋数据表：根据省市区获取房屋数据List
            List<FxBuildingsEntity> fxBuildingsEntities = listBuildings(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());

            if (CollectionUtils.isEmpty(fxBuildingsEntities)) {
                return "该区对应的房屋数据为空，请去'风险评估数据管理-房屋数据管理'添加对应数据！";
            }

            /**
             * 房屋根据用途分为三类：I II III
             * 第Ⅰ类：住宅、公寓、学生和职工集体宿舍、宾馆、招待所等人员居住场所；
             * 第Ⅱ类：办公室、生产车间、教室等工作与学习场所；
             * 第Ⅲ类为娱乐场所、体育馆、车站、候机室、码头等人员较集中的公共场所
             */
            HashMap<String, List<FxBuildingsEntity>> map = classifyByPurpose(fxBuildingsEntities);
            List<FxBuildingsEntity> I = map.get("I");
            List<FxBuildingsEntity> II = map.get("II");
            List<FxBuildingsEntity> III = map.get("III");
            /**
             * 三类各自不同结构类型的面积SI1-SI5,...SIII1-SIII5
             */
            HashMap<String, Float> map1 = countBuildingArea(I);
            HashMap<String, Float> map2 = countBuildingArea(II);
            HashMap<String, Float> map3 = countBuildingArea(III);
            /**
             * 获取该区/县下面的所有易损性
             */
            List<DictItemEntity> structureTypes = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("structureType");
            HashMap<String, HashMap> vuMaps = new HashMap<>();
            for (DictItemEntity dictItemEntity : structureTypes) {
                String structureType = dictItemEntity.getDictItemCode();
                // 每一种结构类型下对应的易损性数据
                HashMap<String, FxVulnerabilityProvinceEntity> vuMap = getVulnerability(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea(), structureType);
                vuMaps.put(structureType, vuMap);
            }
            // 伤亡-重伤率、死亡率
            HashMap<String, FxCasualtyPercentEntity> casualtyMap = getCasualtyPercent(queryParams.getProvince(), queryParams.getCity(), queryParams.getArea());
            // 浮点数四舍五入
            DecimalFormat fnum = new DecimalFormat("##0");
            /**
             * 计算每一条数据的计算值
             */
            for (int i = 0; i < all.size(); i += 4) {
                FxCasulatyEstimateEntity entity = all.get(i);
                /**
                 * 建筑破坏面积*伤亡率
                 */
                Float AR1 = countAR(map1, entity, vuMaps, casualtyMap);
                Float AR2 = countAR(map2, entity, vuMaps, casualtyMap);
                Float AR3 = countAR(map3, entity, vuMaps, casualtyMap);

                // I、II、III类房屋对应昼夜百分比
                Float C1 = getC(entity, "I类");
                Float C2 = getC(entity, "II类");
                Float C3 = getC(entity, "III类");

                /**
                 * η—房屋内人员的密度(单位面积的人口数= 人口数/面积)
                 * 人口用人口普查系统中来，别的系统对接，先展示以县为维度来给的人口
                 * 4/100 人/m2 先给个默认值
                 */
                Float η = 4.0f;
                Float M = C1 * η * AR1 + C2 * η * AR2 + C3 * η * AR3;
                String vulue = fnum.format(M);
                /**
                 * 东城区-VI-重伤-白天下四个烈度的值都是一样的，因为不管哪个烈度都计算轻微到完全破坏的重伤率
                 * 同理死亡也一样，所有计算值只与烈度、人员伤亡、时间段有关，与烈度无关
                 */
                for (int j = 0; j < 4; j++) {
                    FxCasulatyEstimateEntity entityTemp = all.get(i + j);
                    entityTemp.setCalculatedValue(vulue);
                    updateFxCasulatyEstimate(entityTemp);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
        return "计算完成";
    }

    /**
     * 获取昼夜百分比
     *
     * @param entity
     * @param houseType 房屋类别
     * @return
     */
    private Float getC(FxCasulatyEstimateEntity entity, String houseType) {
        // 室内人员昼夜在不同空间位置的百分比
        FxDayNightPercentEntity nightPercentIEntity = dayNightPercentNativeRepository.listFxDayNightPercents(new FxDayNightPercentQueryParams(houseType)).get(0);
        // 昼夜人员在室内百分比
        Float C = 0.0f;
        if ("夜间".equals(entity.getPeriod())) {
            Float nightMax = Float.parseFloat(nightPercentIEntity.getNightMax());
            Float nightMin = Float.parseFloat(nightPercentIEntity.getNightMin());
            C = (nightMin + (nightMax - nightMin) / 2) / 100;
        } else {
            Float dayMax = Float.parseFloat(nightPercentIEntity.getDayMax());
            Float dayMin = Float.parseFloat(nightPercentIEntity.getDayMin());
            C = (dayMin + (dayMax - dayMin) / 2) / 100;
        }
        return C;
    }

    /**
     * 计算某一类面积*伤亡率
     *
     * @param map
     * @param entity
     * @return
     */
    private Float countAR(HashMap<String, Float> map, FxCasulatyEstimateEntity entity, HashMap<String, HashMap> vuMaps, HashMap<String, FxCasualtyPercentEntity> casualtyMap) {
        // A=S*选定区/县对应不同烈度下不同结构类型不同破坏程度的易损性
        HashMap<String, Float> damagesMap = countDamageArea(map, entity, vuMaps);
        // A1:完全破坏面积 A4:轻微破坏面积
        Float A1 = damagesMap.get("A1");
        Float A2 = damagesMap.get("A2");
        Float A3 = damagesMap.get("A3");
        Float A4 = damagesMap.get("A4");
        // 轻微破坏 中等破坏 严重破坏 完全破坏
        FxCasualtyPercentEntity softEntity = casualtyMap.get("1");
        FxCasualtyPercentEntity middleEntity = casualtyMap.get("2");
        FxCasualtyPercentEntity seriousEntity = casualtyMap.get("3");
        FxCasualtyPercentEntity wholeEntity = casualtyMap.get("4");
        Float AR;
        try {
            if ("重伤".equals(entity.getCasulaty())) {
                // 重伤百分比
                Float sp1 = Float.parseFloat(wholeEntity.getSeriousPrercent());
                Float sp2 = Float.parseFloat(seriousEntity.getSeriousPrercent());
                Float sp3 = Float.parseFloat(middleEntity.getSeriousPrercent());
                Float sp4 = Float.parseFloat(softEntity.getSeriousPrercent());
                AR = A1 * sp1 + A2 * sp2 + A3 * sp3 + A4 * sp4;
            } else {
                // 死亡百分比
                Float dp3 = Float.parseFloat(middleEntity.getDeathPrercent());
                Float dp2 = Float.parseFloat(seriousEntity.getDeathPrercent());
                Float dp1 = Float.parseFloat(wholeEntity.getDeathPrercent());
                AR = A1 * dp1 + A2 * dp2 + A3 * dp3;
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
            throw new RuntimeException("该区下面重伤或死亡百分比数据为空,请去'风险评估综合管理-模型参数管理-人员伤亡率'添加数据！");
        }
        return AR;
    }

    /**
     * 获取具体某个区/县下所有破坏程度的伤亡率（重伤和死亡率）
     *
     * @param province
     * @param city
     * @param area
     * @return
     */
    private HashMap<String, FxCasualtyPercentEntity> getCasualtyPercent(String province, String city, String area) {
        FxCasualtyPercentQueryParams queryParams = new FxCasualtyPercentQueryParams();
        queryParams.setProvince(province);
        queryParams.setCity(city);
        queryParams.setArea(area);
        // 破坏程度:轻微破坏、中等破坏、严重破坏、完全破坏
        String[] damageDerees = "1、2、3、4".split("、");
        HashMap<String, FxCasualtyPercentEntity> map = new HashMap<>();
        for (String damageDeree : damageDerees) {
            queryParams.setDamageDegree(damageDeree);
            // 库里应该是有且只有一条数据
            FxCasualtyPercentEntity percentEntitity = casualtyPercentNativeRepository.listFxCasualtyPercents(queryParams).get(0);
            map.put(damageDeree, percentEntitity);
        }
        return map;
    }

    /**
     * S类型*易损性
     *
     * @param sMap   各个结构类型的面积
     * @param entity
     * @return
     */
    private HashMap<String, Float> countDamageArea(HashMap<String, Float> sMap, FxCasulatyEstimateEntity entity, HashMap<String, HashMap> vuMaps) {
        HashMap<String, Float> damageMap = new HashMap<>();
        // 5中结构类型各自对应的面积
        Float S1 = sMap.get("S1");
        Float S2 = sMap.get("S2");
        Float S3 = sMap.get("S3");
        Float S4 = sMap.get("S4");
        Float S5 = sMap.get("S5");
        // 烈度
        String intensity = entity.getIntensity();
        // 易损性map
        HashMap<String, Float> vuMap = new HashMap<>();
        // 结构类型(字典值)
        List<DictItemEntity> structureTypes = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("structureType");
        // 破坏程度(字典值)
        List<DictItemEntity> damageDegrees = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("damageDegree");
        for (int i = 0; i < structureTypes.size(); i++) {
            String structureName = structureTypes.get(i).getDictItemName();
            Float vu = 0.0f;
            // 破坏程度从1开始（0:基本完好用不到）
            for (int j = 1; j < damageDegrees.size(); j++) {
                String damageDegreeName = damageDegrees.get(j).getDictItemCode();
                // 易损性,根据烈度值获取对应的易损性值
                vu = getVuByintensity((FxVulnerabilityProvinceEntity) vuMaps.get(structureName).get(damageDegreeName), intensity);
                // s1d1:结构类型1破坏程度1
                vuMap.put("s" + (i + 1) + "d" + j, vu);
            }
        }
        // 轻微破坏的面积*易损性值
        Float A4 = (S1 * vuMap.get("s1d1") + S2 * vuMap.get("s2d1") + S3 * vuMap.get("s3d1") + S4 * vuMap.get("s4d1") + S5 * vuMap.get("s5d1")) / 100;
        // 中等破坏的面积*易损性值
        Float A3 = (S1 * vuMap.get("s1d2") + S2 * vuMap.get("s2d2") + S3 * vuMap.get("s3d2") + S4 * vuMap.get("s4d2") + S5 * vuMap.get("s5d2")) / 100;
        // 严重破坏的面积*易损性值
        Float A2 = (S1 * vuMap.get("s1d3") + S2 * vuMap.get("s2d3") + S3 * vuMap.get("s3d3") + S4 * vuMap.get("s4d3") + S5 * vuMap.get("s5d3")) / 100;
        // 完全破坏的面积*易损性值
        Float A1 = (S1 * vuMap.get("s1d4") + S2 * vuMap.get("s2d4") + S3 * vuMap.get("s3d4") + S4 * vuMap.get("s4d4") + S5 * vuMap.get("s5d4")) / 100;

        damageMap.put("A1", A1);
        damageMap.put("A2", A2);
        damageMap.put("A3", A3);
        damageMap.put("A4", A4);
        return damageMap;
    }


    /**
     * 获取易损性值
     *
     * @param province
     * @param city
     * @param area
     * @param structureType
     * @return
     */
    private HashMap<String, FxVulnerabilityProvinceEntity> getVulnerability(String province, String city, String area, String structureType) {
        FxVulnerabilityProvinceQueryParams params = new FxVulnerabilityProvinceQueryParams();
        // 省市区
        params.setProvince(province);
        params.setCity(city);
        params.setArea(area);
        // 结构类型
        params.setStructureType(structureType);
        // 破坏程度：1-4，轻微-严重破坏
        String[] damageDegrees = "1,2,3,4".split(",");
        HashMap<String, FxVulnerabilityProvinceEntity> map = new HashMap<>();
        for (String damageDegree : damageDegrees) {
            params.setDamageDegree(damageDegree);
            //Float vu = 0.0f;
            List<FxVulnerabilityProvinceEntity> vulnerabilityProvinces = provinceNativeRepository.listFxVulnerabilityProvinces(params);
            if (!CollectionUtils.isEmpty(vulnerabilityProvinces)) {
                FxVulnerabilityProvinceEntity vulnerabilityProvinceEntity = vulnerabilityProvinces.get(0);
                map.put(damageDegree, vulnerabilityProvinceEntity);
            }
        }
        return map;
    }

    /**
     * 根据烈度来获取对应的易损性
     *
     * @param vulnerabilityProvinceEntity
     * @param intensity
     * @return
     */
    private Float getVuByintensity(FxVulnerabilityProvinceEntity vulnerabilityProvinceEntity, String intensity) {
        Float vu = 0.0f;
        if ("6".equals(intensity)) {
            vu = vulnerabilityProvinceEntity.getVulnerabilityVI();
        }
        if ("7".equals(intensity)) {
            vu = vulnerabilityProvinceEntity.getVulnerabilityVII();
        }
        if ("8".equals(intensity)) {
            vu = vulnerabilityProvinceEntity.getVulnerabilityVIII();
        }
        if ("9".equals(intensity)) {
            vu = vulnerabilityProvinceEntity.getVulnerabilityIX();
        }
        if ("10".equals(intensity)) {
            vu = vulnerabilityProvinceEntity.getVulnerabilityX();
        }
        return vu;
    }


    private FxDamagePercentEntity getDamagePercentEntityByStructureType(String structureType) {
        return damagePercentNativeRepository.listFxDamagePercents(new FxDamagePercentQueryParams(structureType)).get(0);
    }

    /**
     * 计算每一种房屋类型下面每种结构类型的面积
     *
     * @param list
     * @return
     */
    private HashMap<String, Float> countBuildingArea(List<FxBuildingsEntity> list) {
        HashMap<String, Float> map = new HashMap<>();
        // 结构类型
        String[] structureTypes = {"单层砖混", "2-3层砖混", "多层砖混", "钢混框架", "钢混框剪"};
        // 结构类型对应的面积
        float S1 = 0;
        float S2 = 0;
        float S3 = 0;
        float S4 = 0;
        float S5 = 0;
        for (FxBuildingsEntity entity : list) {
            float buildingArea = entity.getBuildingArea();
            String structureType = entity.getStructureType();
            if (StringUtils.isNotBlank(structureType)) {
                if (structureTypes[0].equals(structureType)) {
                    S1 += buildingArea;
                    continue;
                }
                if (structureTypes[1].equals(structureType)) {
                    S2 += buildingArea;
                    continue;
                }
                if (structureTypes[2].equals(structureType)) {
                    S3 += buildingArea;
                    continue;
                }
                if (structureTypes[3].equals(structureType)) {
                    S4 += buildingArea;
                    continue;
                }
                if (structureTypes[4].equals(structureType)) {
                    S5 += buildingArea;
                    continue;
                }
            }
        }
        map.put("S1", S1);
        map.put("S2", S2);
        map.put("S3", S3);
        map.put("S4", S4);
        map.put("S5", S5);
        return map;
    }

    /**
     * 根据房屋用途分类，以map形式返回
     *
     * @param fxBuildingsEntities
     * @return
     */
    private HashMap<String, List<FxBuildingsEntity>> classifyByPurpose(List<FxBuildingsEntity> fxBuildingsEntities) {
        HashMap<String, List<FxBuildingsEntity>> map = new HashMap<>();
        String I = "住宅、公寓、宿舍宿舍、宾馆、招待所、居住";
        String II = "办公室、生产车间、教室、工作、学习";
        String III = "娱乐场所、体育馆、车站、候机室、码头、公共";
        String[] purposeI = I.split("、");
        String[] purposeII = II.split("、");
        String[] purposeIII = III.split("、");
        ArrayList<FxBuildingsEntity> IBuildingsEntities = new ArrayList<>();
        ArrayList<FxBuildingsEntity> IIBuildingsEntities = new ArrayList<>();
        ArrayList<FxBuildingsEntity> IIIBuildingsEntities = new ArrayList<>();
        // 刷选三类
        for (FxBuildingsEntity entity : fxBuildingsEntities) {
            String purpose = entity.getPurpose();
            boolean flag = true;
            // 判断用途是否为第I类
            for (String s : purposeI) {
                if (purpose.contains(s)) {
                    IBuildingsEntities.add(entity);
                    flag = false;
                    break;
                }
            }
            // 判断用途是否为第II类
            if (flag) {
                for (String s : purposeII) {
                    if (purpose.contains(s)) {
                        IIBuildingsEntities.add(entity);
                        flag = false;
                        break;
                    }
                }
            }
            // 判断用途是否为第III类
            if (flag) {
                for (String s : purposeIII) {
                    if (purpose.contains(s)) {
                        IIIBuildingsEntities.add(entity);
                        flag = false;
                        break;
                    }
                }
            }
        }
        map.put("I", IBuildingsEntities);
        map.put("II", IIBuildingsEntities);
        map.put("III", IIIBuildingsEntities);
        return map;
    }

    private List<FxBuildingsEntity> listBuildings(String province, String city, String area) {
        FxBuildingsQueryParams queryParams = new FxBuildingsQueryParams();
        queryParams.setProvince(province);
        queryParams.setCity(city);
        queryParams.setArea(area);
        List<FxBuildingsEntity> buildingsEntities = buildingsNativeRepository.listFxBuildings(queryParams);
        return buildingsEntities;
    }

    @Override
    public void initialize() {
        List<FxCasulatyEstimateEntity> all = fxCasulatyEstimateRepository.findAll();
        if (all != null && all.size() > 0) {
            throw new RuntimeException("请删除所有数据后进行初始化！");
        } else {
            List<DivisionEntity> provinceDivisions = PlatformAPI.getDivisionAPI().getSubDivisions("root");
            for (DivisionEntity provinceDivision : provinceDivisions) {
                // 省
                String province = provinceDivision.getDivisionName();
                // 直辖市
                if ("北京市".equals(province) || "天津市".equals(province) || "上海市".equals(province) || "重庆市".equals(province)) {
                    // 市
                    String city = province;
                    List<DivisionEntity> areaDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(provinceDivision.getDivisionId());
                    for (DivisionEntity areaDivision : areaDivisions) {
                        FxCasulatyEstimateEntity entity = new FxCasulatyEstimateEntity();
                        // 区
                        String area = areaDivision.getDivisionName();
                        entity.setProvince(province);
                        entity.setCity(city);
                        entity.setArea(area);
                        // 类型字典值并且保存
                        saveInitialize(entity);
                    }
                }
                // 省下面的正常市
                else {
                    List<DivisionEntity> cityDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(provinceDivision.getDivisionId());
                    for (DivisionEntity cityDivision : cityDivisions) {
                        // 市
                        String city = cityDivision.getDivisionName();
                        List<DivisionEntity> areaDivisions = PlatformAPI.getDivisionAPI().getSubDivisions(cityDivision.getDivisionId());
                        for (DivisionEntity areaDivision : areaDivisions) {
                            // 区
                            String area = areaDivision.getDivisionName();
                            FxCasulatyEstimateEntity entity = new FxCasulatyEstimateEntity();
                            entity.setProvince(province);
                            entity.setCity(city);
                            entity.setArea(area);
                            // 类型字典值并且保存
                            saveInitialize(entity);
                        }
                    }
                }
            }
        }
    }


    private void saveInitialize(FxCasulatyEstimateEntity entity) {
        // 烈度 6 7 8 9 10
        List<DictItemEntity> intensities = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("earthquakeIntensity");
        for (DictItemEntity intens : intensities) {
            String intensName = intens.getDictItemCode();
            entity.setIntensity(intensName);
            String[] casulaties = "重伤、死亡".split("、");
            // 人员伤亡
            for (String casulaty : casulaties) {
                entity.setCasulaty(casulaty);
                String[] periods = "白天、夜间".split("、");
                // 时间段
                for (String period : periods) {
                    entity.setPeriod(period);
                    // 破坏程度
                    List<DictItemEntity> damageDegrees = PlatformAPI.getDictAPI().getValidDictItemsByDictCode("damageDegree");
                    for (int i = 1; i < damageDegrees.size(); i++) {
                        String damageDegreeName = damageDegrees.get(i).getDictItemCode();
                        entity.setDamageDegree(damageDegreeName);
                        this.saveFxCasulatyEstimate(entity);
                    }
                }
            }
        }
    }

}
